 package cn.modoumama.service.base.impl;
 
 import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.RowBounds;
import org.mybatis.annotation.Table;
import org.mybatis.mapper.interfaces.GenericMapper;
import org.mybatis.util.Ognl;
import org.springframework.transaction.annotation.Transactional;

import cn.modoumama.page.GridDataModel;
import cn.modoumama.page.Page;
import cn.modoumama.service.base.BaseService;

@Transactional(rollbackFor={Exception.class})
 public class BaseServiceImpl<T, PK> implements BaseService<T, PK>{
	protected static final Class<? extends Annotation> MYBATISTABLE = Table.class;
	protected GenericMapper<T, PK> genericMapper;
 
	public void init(){};
	
	public void setGenericMapper(GenericMapper<T, PK> genericMapper){
		this.genericMapper = genericMapper;
	}
 
	public GenericMapper<T, PK> getGenericMapper() {
		return this.genericMapper;
	}
 
	public Integer insert(T entity){
		int count = this.genericMapper.insertModel(entity);
		init();
		return count;
	}
 
	public Integer updateById(T entity){
		int count = this.genericMapper.updateModelById(entity);
		init();
		return count;
	}
	
	public Integer updateNULLById(T entity){
		int count = this.genericMapper.updateNULLById(entity);
		init();
		return count;
	}
 
	@SuppressWarnings("unchecked")
	public Integer mergeById(T entity){
		int count = 0;
		Class<?> clazz = entity.getClass();
		if (clazz.isAnnotationPresent(MYBATISTABLE)) {
			 Table antable = (Table)clazz.getAnnotation(MYBATISTABLE);
			 Arrays.asList(antable.pkId());
			 if (Ognl.isNotEmpty(antable.pkId())) {
		         try {
					String pkId = antable.pkId()[0];
					 pkId = StringUtils.capitalize(pkId);
					 Method method = clazz.getMethod("get" + pkId);
					 T oldEntity = findById((PK)method.invoke(entity));
					if(oldEntity == null){
						insert(entity);
						count = 1;
					}else{
						count = updateById(entity); 
					}
				} catch (Exception e) {
					throw new RuntimeException(e);
				}
		     }else{
		    	 throw new RuntimeException(clazz.getName()+"的注解"+MYBATISTABLE.getName()+"中缺少pkId信息"); 
		     }
		}else{
			throw new RuntimeException(clazz.getName()+"缺少注解"+MYBATISTABLE.getName());
		}
		return count;
	}
 
	public Integer removeById(PK id){
		int count = this.genericMapper.deleteById(id);
		init();
		return count;
	}
	
	public Integer removeByIds(PK[] ids){
		int count = this.genericMapper.deleteByIds(ids);
		init();
		return count;
	}

	@Override
	public Integer deleteByCondition(Map<String, Object> paramMap) {
		int count = this.genericMapper.deleteByCondition(paramMap);
		init();
		return count;
	}
 
	public T findById(PK id){
		if(id != null){
			return this.genericMapper.findObjectById(id);
		}
		return null;
	}
 
	public T findObjectByModel(T entity){
		return this.genericMapper.findObjectByModel(entity);
	}
	
	public T findObjectByModelId(T entity){
		return this.genericMapper.findObjectByModelId(entity);
	}
	 
	public List<T> findListByModel(T entity){
		return this.genericMapper.findListByModel(entity);
	}
	 
	public Integer countByCondition(Map<String, Object> condititon){
		return this.genericMapper.countByCondition(condititon);
	}
	 
	public List<T> findModelsByCondition(Map<String, Object> condititon){
		return this.genericMapper.findModelsByCondition(condititon);
	}
	 
	public GridDataModel findGridDataModelByCondition(Page page){
		Integer totalCount = countByCondition(page.getCondition());
		RowBounds rowBounds = new RowBounds(page.getOffset(), page.getPageSize());
		List<T> results = this.genericMapper.findModelsByCondition(page.getCondition(), rowBounds);
		return new GridDataModel(results, totalCount.intValue());
	}
	 
	public List<T> findModelsByCondition(Page page){
		RowBounds rowBounds = new RowBounds(page.getOffset(), page.getPageSize());
		return this.genericMapper.findModelsByCondition(page.getCondition(), rowBounds);
	}
 }

